#pragma once

#include <boost/logic/tribool.hpp>
#include <boost/tuple/tuple.hpp>


// Forward declaration
struct Request;


/// Parser for incoming requests
class RequestParser
{
public:
	/// Construct ready to parse the request method.
	RequestParser();

	/// Reset to initial parser state.
	void Reset();

	/// Parse some data. The tribool return value is true when a complete request
	/// has been parsed, false if the data is invalid, indeterminate when more
	/// data is required. The InputIterator return value indicates how much of the
	/// input has been consumed.
	template <typename InputIterator>
	boost::tuple<boost::tribool, InputIterator> Parse(Request &req, InputIterator begin, InputIterator end)
	{
		while (begin != end)
		{
			boost::tribool result = Consume(req, *begin++);

			if (result || !result)
				return boost::make_tuple(result, begin);
		}

		boost::tribool result = boost::indeterminate;
		return boost::make_tuple(result, begin);
	}

	private:
		/// Handle the next character of input.
		boost::tribool Consume(Request &req, char input);

		/// Check if a byte is an HTTP character.
		static bool isChar(int c);

		/// Check if a byte is an HTTP control character.
		static bool isCtl(int c);

		/// Check if a byte is defined as an HTTP tspecial character.
		static bool isTspecial(int c);

		/// Check if a byte is a digit.
		static bool isDigit(int c);

		/// The current state of the parser.
		enum State
		{
			MethodStart,
			Method,
			UriStart,
			Uri,
			HttpVersionH,
			HttpVersionT1,
			HttpVersionT2,
			HttpVersionP,
			HttpVersionSlash,
			HttpVersionMajorStart,
			HttpVersionMajor,
			HttpVersionMinorStart,
			HttpVersionMinor,
			ExpectingNewline1,
			HeaderLineStart,
			HeaderLws,
			HeaderName,
			SpaceBeforeHeaderValue,
			HeaderValue,
			ExpectingNewline2,
			ExpectingNewline3
		} _state;
};
